<template>
  <div ref="container" class="canvas-container">
    <!-- 加载状态提示 -->
    <div v-if="loading" class="loading">模型加载中...{{ progress }}%</div>

    <!-- 信息弹窗 -->
    <div v-if="tooltip.visible"
         class="tooltip"
         :style="{
           left: `${tooltip.x}px`,
           top: `${tooltip.y}px`
         }">
      <h3>{{ tooltip.title }}</h3>
      <p>{{ tooltip.content }}</p>
    </div>
  </div>
</template>

<script>
import * as THREE from 'three'
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer'
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass'
import { OutlinePass } from 'three/examples/jsm/postprocessing/OutlinePass'
import { Sky } from 'three/examples/jsm/objects/Sky.js'
export default {
  name: 'FactoryModel',
  data() {
    return {
      // Three.js核心组件
      scene: null,
      camera: null,
      renderer: null,
      controls: null,

      // 后处理相关
      composer: null,
      outlinePass: null,

      // 状态管理
      loading: false,
      progress: 0,
      selectedObject: null,  // 当前选中对象

      // 弹窗配置
      tooltip: {
        visible: false,      // 是否显示
        x: 0,               // 屏幕X坐标
        y: 0,               // 屏幕Y坐标
        title: '设备信息',   // 标题
        content: ''         // 内容
      },
      mouseDownTime: 0,
      mouseDownPos: new THREE.Vector2(),
      isDragging: false,
      // 新增天空相关状态
      sky: null,
      sun: new THREE.Vector3(),
      skyParams: {
        turbidity: 10, //  浑浊度
        rayleigh: 3,  //  瑞利散射系数
        mieCoefficient: 0.005, // 米散射系数
        mieDirectionalG: 0.7, // 米散射方向性
        elevation: 10,   // 太阳高度角（0-90）
        azimuth: 180,   // 太阳方位角（0-360）
        exposure: 1 // 曝光度
      }
    }
  },
  mounted() {
    this.initScene()
    this.loadModel()
    this.setupEventListeners()
    this.animate()
  },
  beforeDestroy() {
    this.cleanupResources()
  },
  methods: {
    /**
     * 初始化3D场景
     */
    initScene() {
      // 创建场景
      this.scene = new THREE.Scene()
      this.scene.background = new THREE.Color(0xcccccc)

      // 初始化透视相机
      this.camera = new THREE.PerspectiveCamera(
        45, // 视野角度
        window.innerWidth / window.innerHeight, // 宽高比
        0.1, // 近裁面
          )
      this.camera.position.set(0, 50, 100); // 初始相机位置

      // 初始化渲染器
      this.renderer = new THREE.WebGLRenderer({
        antialias: true, // 开启抗锯齿
        logarithmicDepthBuffer: true // 解决远处模型闪烁
      })
      this.renderer.setPixelRatio(window.devicePixelRatio)
      this.renderer.setSize(window.innerWidth, window.innerHeight)
      this.$refs.container.appendChild(this.renderer.domElement)

      // 初始化后处理
      this.initPostProcessing()

      // 添加基础光照
      this.addBasicLights()

      // 初始化轨道控制器
      this.controls = new OrbitControls(this.camera, this.renderer.domElement)
      this.controls.enableDamping = true // 启用阻尼惯性
      this.controls.dampingFactor = 0.05 // 阻尼系数

      //
   this.addSky()

    },

    addSky() {
      // 1. 创建天空对象
      this.sky = new Sky()
      this.sky.scale.setScalar(450000)
      this.scene.add(this.sky)

      // 2. 初始化太阳位置
      this.updateSunPosition()

      // 3. 设置天空材质参数
      const skyUniforms = this.sky.material.uniforms
      skyUniforms['turbidity'].value = this.skyParams.turbidity
      skyUniforms['rayleigh'].value = this.skyParams.rayleigh
      skyUniforms['mieCoefficient'].value = this.skyParams.mieCoefficient
      skyUniforms['mieDirectionalG'].value = this.skyParams.mieDirectionalG
      skyUniforms['sunPosition'].value.copy(this.sun)

      // 4. 设置渲染器色调映射
      this.renderer.toneMapping = THREE.ACESFilmicToneMapping
      this.renderer.toneMappingExposure = this.skyParams.exposure
    },

    // 更新太阳位置（关键修复）
    updateSunPosition() {
      const phi = THREE.MathUtils.degToRad(90 - this.skyParams.elevation)
      const theta = THREE.MathUtils.degToRad(this.skyParams.azimuth)
      this.sun.setFromSphericalCoords(1, phi, theta)

      // 同步更新方向光位置
      if (this.directionalLight) {
        this.directionalLight.position.copy(this.sun)
      }

      // 更新天空材质
      if (this.sky) {
        this.sky.material.uniforms['sunPosition'].value.copy(this.sun)
      }
    },

    /**
     * 初始化后处理效果
     */
    initPostProcessing() {
      // 创建效果组合器
      this.composer = new EffectComposer(this.renderer)

      // 添加基础渲染通道
      const renderPass = new RenderPass(this.scene, this.camera)
      this.composer.addPass(renderPass)

      // 配置轮廓描边效果
      this.outlinePass = new OutlinePass(
        new THREE.Vector2(window.innerWidth, window.innerHeight),
        this.scene,
        this.camera
      )
      // 描边参数配置
      this.outlinePass.edgeStrength = 3.0 // 边缘强度
      this.outlinePass.edgeGlow = 0.5     // 边缘光晕
      this.outlinePass.edgeThickness = 2.0 // 边缘厚度
      this.outlinePass.pulsePeriod = 2    // 脉冲周期
      this.outlinePass.visibleEdgeColor.set(0x00ffff) // 可见边缘颜色
      this.outlinePass.hiddenEdgeColor.set(0x0000ff)  // 隐藏边缘颜色

      this.composer.addPass(this.outlinePass)
    },

    /**
     * 添加基础光照
     */
    addBasicLights() {
      // 环境光
      const ambientLight = new THREE.AmbientLight(0xffffff, 0.8)
      this.scene.add(ambientLight)

      // 方向光需要与天空同步
      this.directionalLight = new THREE.DirectionalLight(0xffffff, 1.5)
      this.directionalLight.position.copy(this.sun)
      this.scene.add(this.directionalLight)
    },

    /**
     * 加载FBX模型
     */
    loadModel() {
      this.loading = true
      const loader = new FBXLoader()

      loader.load(
        '/宁海场景.fbx',
        (model) => {
          // 模型加载成功回调
          model.scale.set(0.1, 0.1, 0.1)

          // 遍历模型设置用户数据（示例）
          model.traverse(child => {
            if (child.isMesh) {
              // 为每个模型部件添加示例数据
              child.userData = {
                name: child.name || '未命名部件',
                // info: '设备状态：正常'
              }
            }
          })

          this.scene.add(model)
          this.autoCameraPosition(model)
          this.loading = false
        },
        (xhr) => {
          // 加载进度回调
          this.progress = Math.round((xhr.loaded / xhr.total) * 100)
        },
        (error) => {
          // 错误处理
          console.error('模型加载失败:', error)
          this.loading = false
        }
      )
    },

    /**
     * 处理点击事件
     * @param {MouseEvent} event 鼠标事件
     */
    handleClick(event) {
      // 排除拖动操作
      if (this.isDragging || this.controls.isRotating || this.controls.isPanning) {
        return
      }

      // 判断移动距离阈值（5像素）
      const moveThreshold = 5
      const deltaX = Math.abs(event.clientX - this.mouseDownPos.x)
      const deltaY = Math.abs(event.clientY - this.mouseDownPos.y)

      if (deltaX > moveThreshold || deltaY > moveThreshold) {
        return
      }
      const mouse = new THREE.Vector2()
      const rect = this.renderer.domElement.getBoundingClientRect()

      mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1
      mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1

      const raycaster = new THREE.Raycaster()
      raycaster.setFromCamera(mouse, this.camera)

      const intersects = raycaster.intersectObjects(this.scene.children, true)

      if (intersects.length > 0) {
        const selected = intersects[0].object

        // 如果是新选中的对象
        if (this.selectedObject !== selected) {
          this.selectedObject = selected
          this.outlinePass.selectedObjects = [selected]
          this.showTooltip(selected, event)
        }
      } else {
        this.clearSelection()
      }
    },

    /**
     * 显示Tooltip
     * @param {THREE.Object3D} object 选中的3D对象
     * @param {MouseEvent} event 鼠标事件
     */
    showTooltip(object, event) {
      this.tooltip = {
        visible: true,
        x: event.clientX + 15,
        y: event.clientY + 15,
        title: object.userData.name || '设备信息',
        content: object.userData.info || '暂无详细信息'
      }
    },

    /**
     * 清除当前选择
     */
    clearSelection() {
      this.selectedObject = null
      this.outlinePass.selectedObjects = []
      this.tooltip.visible = false
    },

    /**
     * 自动调整相机位置
     * @param {THREE.Object3D} model 模型对象
     */
    autoCameraPosition(model) {
      const box = new THREE.Box3().setFromObject(model)
      const center = box.getCenter(new THREE.Vector3())
      const size = box.getSize(new THREE.Vector3()).length()

      // 计算最佳观察距离
      const fitDistance = size * 1.5

      // 设置相机位置

      this.camera.lookAt(center)

      // 更新控制器目标
      this.controls.target.copy(center)

      // 设置控制器最远距离限制
      this.controls.maxDistance = fitDistance * 3
    },

    /**
     * 窗口大小变化处理
     */
    onWindowResize() {
      // 更新相机比例
      this.camera.aspect = window.innerWidth / window.innerHeight
      this.camera.updateProjectionMatrix()

      // 更新渲染器和后处理
      this.renderer.setSize(window.innerWidth, window.innerHeight)
      this.composer.setSize(window.innerWidth, window.innerHeight)
    },

    /**
     * 动画循环
     */
    animate() {
      requestAnimationFrame(this.animate)

      // 更新控制器状态
      this.controls.update()

      // 渲染后处理效果
      this.composer.render()
      if (this.selectedObject) {
        const vector = new THREE.Vector3()
        this.selectedObject.getWorldPosition(vector)
        vector.project(this.camera)

        const x = (vector.x * 0.5 + 0.5) * window.innerWidth
        const y = (vector.y * -0.5 + 0.5) * window.innerHeight

        this.tooltip.x = x + 15
        this.tooltip.y = y + 15
      }
    },

    /**
     * 清理资源
     */
    cleanupResources() {
      // 移除事件监听
      window.removeEventListener('resize', this.onWindowResize)
      const canvas = this.renderer.domElement
      canvas.removeEventListener('mousedown', this.handleMouseDown)
      canvas.removeEventListener('mousemove', this.handleMouseMove)
      canvas.removeEventListener('mouseup', this.handleMouseUp)
      canvas.removeEventListener('click', this.handleClick)
      // 释放WebGL资源
      this.renderer.dispose()

      // 清理后处理通道
      this.composer.passes.forEach(pass => pass.dispose())

      // 移除画布元素
      this.$refs.container.removeChild(this.renderer.domElement)
    },

    /**
     * 设置事件监听器
     */
    setupEventListeners() {
      window.addEventListener('resize', this.onWindowResize)
      const canvas = this.renderer.domElement
      canvas.addEventListener('mousedown', this.handleMouseDown)
      canvas.addEventListener('mousemove', this.handleMouseMove)
      canvas.addEventListener('mouseup', this.handleMouseUp)
      canvas.addEventListener('click', this.handleClick)
    },
    // 鼠标按下处理
    handleMouseDown(event) {
      this.mouseDownTime = Date.now()
      this.mouseDownPos.set(event.clientX, event.clientY)
      this.isDragging = false
    },
    // 鼠标移动处理
    handleMouseMove() {
      if (Date.now() - this.mouseDownTime > 50) {
        this.isDragging = true
      }
    },

    // 鼠标释放处理
    handleMouseUp() {
      this.isDragging = false
    },
  }
}
</script>

<style scoped>
.canvas-container {
  width: 100vw;
  height: 100vh;
  overflow: hidden;
  position: relative;
}

/* 加载提示样式 */
.loading {
  position: absolute;
  top: 20px;
  left: 50%;
  transform: translateX(-50%);
  color: white;
  background: rgba(0,0,0,0.7);
  padding: 8px 16px;
  border-radius: 4px;
  font-family: Arial;
  z-index: 100;
}

/* Tooltip样式 */
.tooltip {
  position: fixed;
  background: rgba(0, 0, 0, 0.8);
  color: white;
  padding: 12px;
  border-radius: 6px;
  pointer-events: none; /* 防止遮挡点击事件 */
  min-width: 200px;
  max-width: 300px;
  z-index: 100;
  backdrop-filter: blur(2px);
  border: 1px solid rgba(255,255,255,0.1);
  box-shadow: 0 4px 12px rgba(0,0,0,0.25);
}

.tooltip h3 {
  margin: 0 0 8px 0;
  font-size: 16px;
  color: #00ffff;
}

.tooltip p {
  margin: 0;
  font-size: 14px;
  line-height: 1.5;
}
</style>